﻿using Application.Common.Interfaces;
using Application.Features.Users.EventHandlers;
using Azure.Core;
using Common.Attributes;
using Common.Services;
using Domain.Entities;
using Domain.Entities.Identity;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Application.Features.Users.Commands.Update;

/// <summary>
/// 给用户分配角色
/// </summary>
[Description("分配角色")]
[GroupDescription(("用户管理"))]
public class AssignRoleToUserCommand : IRequest<bool>
{
    /// <summary>
    /// 用户唯一标识
    /// </summary>
    [Required(ErrorMessage = "用户唯一标识必填")]
    public List<long> UserIds { get; set; }

    /// <summary>
    /// 角色唯一标识
    /// </summary>
    public List<long>? RoleIds { get; set; }
}

/// <summary>
/// 处理程序
/// </summary>
public class AssignRoleToUserCommandHandler : IRequestHandler<AssignRoleToUserCommand, bool>
{
    private readonly IApplicationDbContext _context;
    private readonly ISnowFlakeService _snowFlakeService;
    private readonly IMediator _mediator;

    public AssignRoleToUserCommandHandler(
        IApplicationDbContext context,
        ISnowFlakeService snowFlakeService,
        IMediator mediator)
    {
        _context = context;
        _snowFlakeService = snowFlakeService;
        _mediator = mediator;
    }

    /// <summary>
    /// 业务逻辑
    /// </summary>
    /// <param name="request">请求参数</param>
    /// <param name="cancellationToken">取消标记</param>
    /// <returns>返回处理结果</returns>
    public async Task<bool> Handle(AssignRoleToUserCommand request, CancellationToken cancellationToken)
    {
        var userRolesToDelete = await _context.UserRoles
            .Include(u => u.User)
            .Where(x => request.UserIds.Contains(x.UserId))
            .ToListAsync();

        var receiveMessageUsers = new HashSet<User>();

        if (userRolesToDelete.Any())
        {
            receiveMessageUsers = userRolesToDelete.Select(x => x.User).ToHashSet();
            _context.UserRoles.RemoveRange(userRolesToDelete);
        }
        else
        {
            receiveMessageUsers = _context.Users.Where(x => request.UserIds.Contains(x.Id)).ToHashSet();
        }

        if (request.RoleIds == null)
        {
            await _mediator.Publish(new AssignRoleToUserEvent<HashSet<User>>(receiveMessageUsers));
            return true;
        }

        request.UserIds = request.UserIds.Distinct().ToList();
        request.RoleIds = request.RoleIds?.Distinct().ToList();

        var addUserRoles = new List<UserRole>();
        foreach (var userId in request.UserIds)
        {
            foreach (var roleId in request?.RoleIds!)
            {
                var userRole = new UserRole()
                {
                    Id = _snowFlakeService.GenerateId(),
                    UserId = userId,
                    RoleId = roleId
                };
                addUserRoles.Add(userRole);
            }
        }

        await _context.UserRoles.AddRangeAsync(addUserRoles);
        await _mediator.Publish(new AssignRoleToUserEvent<HashSet<User>>(receiveMessageUsers));

        return true;
    }
}